home *** CD-ROM | disk | FTP | other *** search
/ Kit PC World De Ampliacion De Windows 95 / Kit PC World de ampliacion de Windows 95.iso / internet / sweeper / samples / olecon~1 / controls / button / button~1.cpp < prev    next >
Text File  |  1995-11-28  |  18KB  |  644 lines

  1. //=--------------------------------------------------------------------------=
  2. // ButtonCtl.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright  1995  Microsoft Corporation.  All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. #include "IPServer.H"
  13.  
  14. #include "Guids.H"
  15. #include "ButtonCtl.H"
  16. #include "LocalObj.H"
  17. #include "Util.H"
  18. #include "Globals.H"
  19. #include "Resource.H"
  20.  
  21. #include <windowsx.h>
  22.  
  23. // for ASSERT and FAIL
  24. //
  25. SZTHISFILE
  26.  
  27. // local private functions
  28. //
  29. short            _GetShiftState(void);
  30.  
  31. // these are used for events
  32. //
  33. #define LEFT_BUTTON     0x01
  34. #define RIGHT_BUTTON    0x02
  35. #define MIDDLE_BUTTON   0x04
  36.  
  37.  
  38. //=--------------------------------------------------------------------------=
  39. // for persistence
  40. //
  41. #define STREAMHDR_MAGIC    0x12345678
  42.  
  43. typedef struct {
  44.  
  45.     DWORD dwMagic;
  46.     DWORD dwVersion;
  47.     DWORD cbSize;
  48.  
  49. } STREAMHDR;
  50.  
  51. WCHAR wszCaption [] = L"Caption";
  52.  
  53.  
  54. //=--------------------------------------------------------------------------=
  55. // all the events in this control
  56. //
  57. // TODO: add events here ...
  58. //
  59. VARTYPE rgI2I2I4I4 [] = { VT_I2, VT_I2, VT_I4, VT_I4 };
  60.  
  61. typedef enum {
  62.  
  63.     ButtonEvent_Click = 0,
  64.     ButtonEvent_DblClick = 1,
  65.     ButtonEvent_MouseDown = 2,
  66.     ButtonEvent_MouseMove = 3,
  67.     ButtonEvent_MouseUp = 4
  68.  
  69. } BUTTONEVENTS;
  70.  
  71. EVENTINFO m_rgEvents [] = {
  72.     { DISPID_CLICK, 0, NULL },
  73.     { DISPID_DBLCLICK, 0, NULL },
  74.     { DISPID_MOUSEDOWN, 4, rgI2I2I4I4 },
  75.     { DISPID_MOUSEMOVE, 4, rgI2I2I4I4 },
  76.     { DISPID_MOUSEUP, 4, rgI2I2I4I4 },
  77. };
  78.  
  79.  
  80. //=--------------------------------------------------------------------------=
  81. // array describing all of our property pages.  these clsids are typically
  82. // in guids.h
  83. //
  84. // TODO: add any additional property page guids here ...
  85. //
  86. const GUID *rgButtonPropPages [] = {
  87.     &CLSID_ButtonGeneralPage
  88. };
  89.  
  90. //=--------------------------------------------------------------------------=
  91. // Custum Verb information
  92. //
  93. // TODO: add any custom verbs here in an array, using the VERBINFO structure.
  94. //       then mark the controld def'n in ButtonCtl.H with
  95. //       this verb array
  96. //
  97.  
  98.  
  99. //=--------------------------------------------------------------------------=
  100. // CButtonControl::Create
  101. //=--------------------------------------------------------------------------=
  102. // global static function that creates an instance of the control an returns
  103. // an IUnknown pointer for it.
  104. //
  105. // Parameters:
  106. //    IUnknown *        - [in] controlling unknown for aggregation
  107. //
  108. // Output:
  109. //    IUnknown *        - new object.
  110. //
  111. // Notes:
  112. //
  113. IUnknown *CButtonControl::Create
  114. (
  115.     IUnknown *pUnkOuter
  116. )
  117. {
  118.     // make sure we return the private unknown so that we support aggegation
  119.     // correctly!
  120.     //
  121.     CButtonControl *pNew = new CButtonControl(pUnkOuter);
  122.     return pNew->PrivateUnknown();
  123. }
  124.  
  125. //=--------------------------------------------------------------------------=
  126. // CButtonControl::CButtonControl
  127. //=--------------------------------------------------------------------------=
  128. // "Being born is like being kidnapped.  And then sold into slavery."
  129. //    - andy warhol (1928 - 87)
  130. //
  131. // Parameters:
  132. //    IUnknown *        - [in]
  133. //
  134. // Notes:
  135. //
  136. #pragma warning(disable:4355)  // using 'this' in constructor
  137. CButtonControl::CButtonControl
  138. (
  139.     IUnknown *pUnkOuter
  140. )
  141. : COleControl(pUnkOuter, OBJECT_TYPE_CTLBUTTON, (IDispatch *)this)
  142. {
  143.     // zero out the persistent state structure.
  144.     //
  145.     memset(&m_state, 0, sizeof(BUTTONCTLSTATE));
  146.  
  147.     // TODO: initialize anything you need to here.
  148.     //
  149.     lstrcpy(m_state.szCaption, "Button");
  150. }
  151. #pragma warning(default:4355)  // using 'this' in constructor
  152.  
  153. //=--------------------------------------------------------------------------=
  154. // CButtonControl::~CButtonControl
  155. //=--------------------------------------------------------------------------=
  156. // "We all labour against our own cure, for death is the cure of all diseases"
  157. //    - Sir Thomas Browne (1605 - 82)
  158. //
  159. // Notes:
  160. //
  161. CButtonControl::~CButtonControl ()
  162. {
  163.     // TODO: clean up anything here.
  164. }
  165.  
  166. //=--------------------------------------------------------------------------=
  167. // CButtonControl:RegisterClassData
  168. //=--------------------------------------------------------------------------=
  169. // register the window class information for your control here.
  170. // this information will automatically get cleaned up for you on DLL shutdown.
  171. //
  172. // Output:
  173. //    BOOL            - FALSE means fatal error.
  174. //
  175. // Notes:
  176. //
  177. BOOL CButtonControl::RegisterClassData
  178. (
  179.     void
  180. )
  181. {
  182.     WNDCLASS wndclass;
  183.  
  184.     // subclass a windows BUTTON control.
  185.     //
  186.     if (!::GetClassInfo(g_hInstance, "BUTTON", &wndclass))
  187.         return FALSE;
  188.  
  189.     SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON) = (WNDPROC)wndclass.lpfnWndProc;
  190.     wndclass.lpfnWndProc = COleControl::ControlWindowProc;
  191.     wndclass.lpszClassName = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLBUTTON);
  192.  
  193.     return RegisterClass(&wndclass);
  194. }
  195.  
  196. //=--------------------------------------------------------------------------=
  197. // CButtonControl::BeforeCreateWindow
  198. //=--------------------------------------------------------------------------=
  199. // called just before the window is created.  Great place to set up the
  200. // window title, etc, so that they're passed in to the call to CreateWindowEx.
  201. // speeds things up slightly.
  202. //
  203. // Notes:
  204. //
  205. void CButtonControl::BeforeCreateWindow
  206. (
  207.     void
  208. )
  209. {
  210.     // TODO: users should modify m_dwWindowStyle, m_dwWindowStyleEx, m_szWindowTitle
  211.     // et al here so that the call to createwindow has as much information as
  212.     // possible.
  213.     // if you don't use this function, then you can probably just remove it.
  214.     //
  215.     m_szWindowTitle = m_state.szCaption;
  216. }
  217.  
  218. //=--------------------------------------------------------------------------=
  219. // CButtonControl::AfterCreateWindow
  220. //=--------------------------------------------------------------------------=
  221. // we have to override this so we can set up the font from the hosts
  222. // ambient font.
  223. //
  224. // Notes:
  225. //
  226. void CButtonControl::AfterCreateWindow
  227. (
  228.     void
  229. )
  230. {
  231.     IFont *pFont;
  232.     HFONT  hFont;
  233.  
  234.     // get the HFONT for the form's ambient font.
  235.     //
  236.     GetAmbientFont(&pFont);
  237.     pFont->get_hFont(&hFont);
  238.  
  239.     SendMessage(m_hwnd, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE, 0));
  240.     pFont->Release();
  241. }
  242.  
  243. //=--------------------------------------------------------------------------=
  244. // CButtonControl::InternalQueryInterface
  245. //=--------------------------------------------------------------------------=
  246. // qi for things only we support.
  247. //
  248. // Parameters:
  249. // Parameters:
  250. //    REFIID        - [in]  interface they want
  251. //    void **       - [out] where they want to put the resulting object ptr.
  252. //
  253. // Output:
  254. //    HRESULT       - S_OK, E_NOINTERFACE
  255. //
  256. // Notes:
  257. //
  258. HRESULT CButtonControl::InternalQueryInterface
  259. (
  260.     REFIID  riid,
  261.     void  **ppvObjOut
  262. )
  263. {
  264.     IUnknown *pUnk;
  265.  
  266.     *ppvObjOut = NULL;
  267.  
  268.     // TODO: if you want to support any additional interrfaces, then you should
  269.     // indicate that here.  never forget to call COleControl's version in the
  270.     // case where you don't support the given interface.
  271.     //
  272.     if (DO_GUIDS_MATCH(riid, IID_IButton)) {
  273.         pUnk = (IUnknown *)(IButton *)this;
  274.     } else{
  275.         return COleControl::InternalQueryInterface(riid, ppvObjOut);
  276.     }
  277.  
  278.     pUnk->AddRef();
  279.     *ppvObjOut = (void *)pUnk;
  280.     return S_OK;
  281. }
  282.  
  283. //=--------------------------------------------------------------------------=
  284. // CButtonControl::LoadTextState
  285. //=--------------------------------------------------------------------------=
  286. // load in our text state for this control.
  287. //
  288. // Parameters:
  289. //    IPropertyBag *        - [in] property bag to read from
  290. //    IErrorLog *           - [in] errorlog object to use with proeprty bag
  291. //
  292. // Output:
  293. //    HRESULT
  294. //
  295. // Notes:
  296. //    - NOTE: if you have a binary object, then you should pass an unknown
  297. //      pointer to the property bag, and it will QI it for IPersistStream, and
  298. //      get said object to do a Load()
  299. //
  300. STDMETHODIMP CButtonControl::LoadTextState
  301. (
  302.     IPropertyBag *pPropertyBag,
  303.     IErrorLog    *pErrorLog
  304. )
  305. {
  306.     VARIANT v;
  307.  
  308.     v.vt = VT_BSTR;
  309.     v.bstrVal = NULL;
  310.  
  311.     // try to load in the property.  if we can't get it, then leave
  312.     // things at their default.
  313.     //
  314.     pPropertyBag->Read(wszCaption, &v, pErrorLog);
  315.     if (v.bstrVal) {
  316.         MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
  317.         lstrcpyn(m_state.szCaption, psz, sizeof(m_state.szCaption));
  318.         VariantClear(&v);
  319.     }
  320.  
  321.     return S_OK;
  322. }
  323.  
  324. //=--------------------------------------------------------------------------=
  325. // CButtonControl::LoadBinaryState
  326. //=--------------------------------------------------------------------------=
  327. // loads in our binary state using streams.
  328. //
  329. // Parameters:
  330. //    IStream *            - [in] stream to write to.
  331. //
  332. // Output:
  333. //    HRESULT
  334. //
  335. // Notes:
  336. //
  337. STDMETHODIMP CButtonControl::LoadBinaryState
  338. (
  339.     IStream *pStream
  340. )
  341. {
  342.     STREAMHDR sh;
  343.     HRESULT   hr;
  344.  
  345.     // first read in the streamhdr, and make sure we like what we're getting
  346.     //
  347.     hr = pStream->Read(&sh, sizeof(sh), NULL);
  348.     RETURN_ON_FAILURE(hr);
  349.  
  350.     // sanity check
  351.     //
  352.     if (sh.dwMagic != STREAMHDR_MAGIC || sh.cbSize != sizeof(m_state))
  353.         return E_UNEXPECTED;
  354.  
  355.     // read in the control state information
  356.     //
  357.     hr = pStream->Read(&(m_state), sizeof(m_state), NULL);
  358.     RETURN_ON_FAILURE(hr);
  359.  
  360.     return S_OK;
  361. }
  362.  
  363. //=--------------------------------------------------------------------------=
  364. // CButtonControl::SaveTextState
  365. //=--------------------------------------------------------------------------=
  366. // saves out the text state for this control using a property bag.
  367. //
  368. // Parameters:
  369. //    IPropertyBag *        - [in] the property bag with which to work.
  370. //    BOOL                  - [in] if TRUE, then write out ALL properties, even
  371. //                            if they're their the default value ...
  372. //
  373. // Output:
  374. //    HRESULT
  375. //
  376. // Notes:
  377. //
  378. STDMETHODIMP CButtonControl::SaveTextState
  379. (
  380.     IPropertyBag *pPropertyBag,
  381.     BOOL          fWriteDefaults
  382. )
  383. {
  384.     HRESULT hr;
  385.     VARIANT v;
  386.  
  387.     v.vt = VT_BSTR;
  388.     v.bstrVal = BSTRFROMANSI(m_state.szCaption);
  389.     RETURN_ON_NULLALLOC(v.bstrVal);
  390.  
  391.     // this control currently only persists out the caption property
  392.     //
  393.     hr = pPropertyBag->Write(wszCaption, &v);
  394.     VariantClear(&v);
  395.     return hr;
  396. }
  397.  
  398. //=--------------------------------------------------------------------------=
  399. // CButtonControl::SaveBinaryState
  400. //=--------------------------------------------------------------------------=
  401. // save out the binary state for this control, using the given IStream object.
  402. //
  403. // Parameters:
  404. //    IStream  *             - [in] save to which you should save.
  405. //
  406. // Output:
  407. //    HRESULT
  408. //
  409. // Notes:
  410. //    - it is important that you seek to the end of where you saved your
  411. //      properties when you're done with the IStream.
  412. //
  413. STDMETHODIMP CButtonControl::SaveBinaryState
  414. (
  415.     IStream *pStream
  416. )
  417. {
  418.     STREAMHDR sh = { STREAMHDR_MAGIC, MAKELONG(1, 0), sizeof(m_state) };
  419.     HRESULT hr;
  420.  
  421.     // write out the stream hdr.
  422.     //
  423.     hr = pStream->Write(&sh, sizeof(sh), NULL);
  424.     RETURN_ON_FAILURE(hr);
  425.  
  426.     // write out he control state information
  427.     //
  428.     hr = pStream->Write(&m_state, sizeof(m_state), NULL);
  429.     return hr;
  430. }
  431.  
  432. //=--------------------------------------------------------------------------=
  433. // CButtonControl::OnDraw
  434. //=--------------------------------------------------------------------------=
  435. // "I don't very much enjoy looking at paintings in general.  i know too
  436. //  much about them.  i take them apart."
  437. //    - georgia o'keeffe (1887-1986)
  438. //
  439. // Parameters:
  440. //    HDC                - [in]  HDC to draw to
  441. //    LPCRECTL           - [in]  rect we're drawing to
  442. //    LPCRECTL           - [in]  window extent and origin for meta-files
  443. //    HDC                - [in]  HIC for target device
  444. //
  445. // Output:
  446. //    HRESULT
  447. //
  448. // Notes:
  449. //
  450. HRESULT CButtonControl::OnDraw
  451. (
  452.     HDC      hdcDraw,
  453.     LPCRECTL prcBounds,
  454.     LPCRECTL prcWBounds,
  455.     HDC      hicTargetDevice
  456. )
  457. {
  458.     // TODO: put your drawing code here ...
  459.     //
  460.     return DoSuperClassPaint(hdcDraw, prcBounds);
  461. }
  462.  
  463. //=--------------------------------------------------------------------------=
  464. // CButtonControl::WindowProc
  465. //=--------------------------------------------------------------------------=
  466. // window procedure for this control.  nothing terribly exciting.
  467. //
  468. // Parameters:
  469. //     see win32sdk on window procs.
  470. //
  471. // Notes:
  472. //
  473. LRESULT CButtonControl::WindowProc
  474. (
  475.     HWND   hwnd,
  476.     UINT   msg,
  477.     WPARAM wParam,
  478.     LPARAM lParam
  479. )
  480. {
  481.     switch (msg) {
  482.         case WM_LBUTTONDOWN:
  483.         case WM_RBUTTONDOWN:
  484.         case WM_MBUTTONDOWN:
  485.             {
  486.             short s = (msg == WM_LBUTTONDOWN) ? LEFT_BUTTON : ((msg == WM_RBUTTONDOWN) ? RIGHT_BUTTON : MIDDLE_BUTTON);
  487.             FireEvent(&(m_rgEvents[ButtonEvent_MouseDown]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
  488.             }
  489.             break;
  490.  
  491.         case WM_LBUTTONDBLCLK:
  492.         case WM_RBUTTONDBLCLK:
  493.         case WM_MBUTTONDBLCLK:
  494.             FireEvent(&(m_rgEvents[ButtonEvent_DblClick]));
  495.             break;
  496.  
  497.         case WM_RBUTTONUP:
  498.         case WM_LBUTTONUP:
  499.         case WM_MBUTTONUP:
  500.             {
  501.             short s = (msg == WM_LBUTTONUP) ? LEFT_BUTTON : ((msg == WM_RBUTTONUP) ? RIGHT_BUTTON : MIDDLE_BUTTON);
  502.             FireEvent(&(m_rgEvents[ButtonEvent_MouseUp]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
  503.             }
  504.             break;
  505.  
  506.         case WM_MOUSEMOVE:
  507.             {
  508.             short s = (wParam & MK_LBUTTON) ? LEFT_BUTTON : ((wParam & MK_RBUTTON) ? RIGHT_BUTTON : ((wParam & MK_MBUTTON) ? MIDDLE_BUTTON : 0));
  509.             FireEvent(&(m_rgEvents[ButtonEvent_MouseMove]), s, _GetShiftState(), (long)LOWORD(lParam), (long)HIWORD(lParam));
  510.             }
  511.             break;
  512.  
  513.  
  514.         case OCM_COMMAND:
  515.             switch (LOWORD(wParam)) {
  516.                 case BN_CLICKED:
  517.                     FireEvent(&(m_rgEvents[ButtonEvent_Click]));
  518.                     break;
  519.             }
  520.             break;
  521.     }
  522.  
  523.     // pass anything else on to the superproc.
  524.     //
  525.     return CallWindowProc((FARPROC)SUBCLASSWNDPROCOFCONTROL(OBJECT_TYPE_CTLBUTTON), hwnd, msg, wParam, lParam);
  526. }
  527.  
  528. //=--------------------------------------------------------------------------=
  529. // CButtonControl::AboutBox
  530. //=--------------------------------------------------------------------------=
  531. // prints up an about box.  fweeeee.
  532. //
  533. // Notes:
  534. //
  535. void CButtonControl::AboutBox
  536. (
  537.     void
  538. )
  539. {
  540.     // TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
  541.     // they wanted a slightly more interesting About Box ...  you should
  542.     // still call ModalDialog first, however.
  543.     //
  544.     ModalDialog(TRUE);
  545.     MessageBox(NULL, "This is My Control", "About Button", MB_OK | MB_TASKMODAL);
  546.     ModalDialog(FALSE);
  547. }
  548.  
  549. //=--------------------------------------------------------------------------=
  550. // CButtonControl::get_Caption    [IButton]
  551. //=--------------------------------------------------------------------------=
  552. // returns current caption
  553. //
  554. // Parameters:
  555. //    BSTR *        - [out] duh
  556. //
  557. // Output:
  558. //    HRESULT
  559. //
  560. // Notes:
  561. //
  562. STDMETHODIMP CButtonControl::get_Caption
  563. (
  564.     BSTR *pbstrCaption
  565. )
  566. {
  567.     CHECK_POINTER(pbstrCaption);
  568.  
  569.     *pbstrCaption = (*m_state.szCaption) ? BSTRFROMANSI(m_state.szCaption) : SysAllocString(L"");
  570.  
  571.     return (*pbstrCaption) ? S_OK : E_OUTOFMEMORY;
  572. }
  573. //=--------------------------------------------------------------------------=
  574. // CButtonControl::put_Caption    [IButton]
  575. //=--------------------------------------------------------------------------=
  576. // sets the new caption
  577. //
  578. // Parameters:
  579. //    BSTR            - [in] duh
  580. //
  581. // Output:
  582. //    HRESULT
  583. //
  584. // Notes:
  585. //
  586. STDMETHODIMP CButtonControl::put_Caption
  587. (
  588.     BSTR bstrCaption
  589. )
  590. {
  591.     // get an ANSI pointer, so we can stuff it in our local buffer for captions!
  592.     //
  593.     if (!bstrCaption) bstrCaption = L"";
  594.     MAKE_ANSIPTR_FROMWIDE(pszCaption, bstrCaption);
  595.  
  596.     // if it hasn't changed, don't waste any time.
  597.     //
  598.     if (!lstrcmp(m_state.szCaption, pszCaption))
  599.         return S_OK;
  600.  
  601.     // copy it over
  602.     //
  603.     lstrcpyn(m_state.szCaption, pszCaption, sizeof(m_state.szCaption));
  604.  
  605.     // update the window, if appropriate.
  606.     //
  607.     if (m_hwnd) {
  608.         Button_SetText(m_hwnd, m_state.szCaption);
  609.         InvalidateControl(NULL);
  610.     }
  611.  
  612.     // update anybody who cares about property changes and mark ourselves
  613.     // as dirty
  614.     //
  615.     PropertyChanged(DISPID_CAPTION);
  616.     m_fDirty = TRUE;
  617.     return S_OK;
  618. }
  619.  
  620.  
  621. //=--------------------------------------------------------------------------=
  622. // _GetShiftState    [standard helper!]
  623. //=--------------------------------------------------------------------------=
  624. // used by people to get shift state information
  625. //
  626. // Output:
  627. //    short        - mask of shift, ctrl and alt keys
  628. //
  629. // Notes:
  630. //
  631. short _GetShiftState
  632. (
  633.     void
  634. )
  635. {
  636.     BOOL bShift = (GetKeyState(VK_SHIFT) < 0);
  637.     BOOL bCtrl  = (GetKeyState(VK_CONTROL) < 0);
  638.     BOOL bAlt   = (GetKeyState(VK_MENU) < 0);
  639.  
  640.     return (short)(bShift + (bCtrl << 1) + (bAlt << 2));
  641.  
  642. }
  643.  
  644.